import os
import sys
import datetime
from typing import Union


class Log(object):
    FLAG_I = 0x01
    FLAG_D = 0x02
    FLAG_W = 0x04
    FLAG_E = 0x08
    _flags = FLAG_I | FLAG_D | FLAG_W | FLAG_E

    OUT_STDOUT = 0x01
    OUT_FILE = 0x02
    _OUT = OUT_STDOUT | OUT_FILE

    _SCRIPT_DIR: str = os.path.dirname(sys.argv[0])
    _LOG_DIR: str = os.path.join(_SCRIPT_DIR, 'log')

    @staticmethod
    def flag() -> int:
        return Log._flags

    @staticmethod
    def config_out(out: int):
        Log._OUT = out

    @staticmethod
    def set_flag(flag: int):
        Log._flags = flag

    @staticmethod
    def raw(level: str, tag: str, msg: Union[None, str] = None):
        time = datetime.datetime.now()
        date_time_tag = time.strftime('%Y-%m-%d %H:%M:%S')

        if msg is None:
            message = '[%s] %s: %s' % (date_time_tag, level, tag)
        else:
            message = '[%s] %s: [%s] %s' % (date_time_tag, level, tag, msg)

        if Log._OUT & Log.OUT_STDOUT:
            print(message)

        if Log._OUT & Log.OUT_FILE:
            os.makedirs(Log._LOG_DIR, exist_ok=True)
            file_path = os.path.join(Log._LOG_DIR, time.strftime('%Y-%m-%d.log'))
            with open(file_path, 'a+', encoding='utf8') as file:
                file.write(message)
                file.write('\n')

    @staticmethod
    def i(tag: str, msg: Union[None, str] = None):
        if Log._flags & Log.FLAG_I:
            Log.raw('INFO', tag, msg)

    @staticmethod
    def d(tag: str, msg: Union[None, str] = None):
        if Log._flags & Log.FLAG_D:
            Log.raw('DEBUG', tag, msg)

    @staticmethod
    def w(tag: str, msg: Union[None, str] = None):
        if Log._flags & Log.FLAG_W:
            Log.raw('WARNING', tag, msg)

    @staticmethod
    def e(tag: str, msg: Union[None, str] = None):
        if Log._flags & Log.FLAG_E:
            Log.raw('ERROR', tag, msg)
